#pragma once
#include "..\stdafx.h"
#include <list>
#include <map>

typedef struct tagPOINTU
{
	ULONG x;
	ULONG y;
#ifdef __cplusplus
	bool operator ==(const tagPOINTU& point)
	{
		return (x == point.x && y == point.y);
	}

	bool operator !=(const tagPOINTU& point)
	{
		return (x != point.x || y != point.y);
	}

	tagPOINTU operator +=(const POINT& point)
	{
		x += point.x;
		y += point.y;
		return *this;
	}
#endif
} POINTU;


struct MAP_INFO
{
	float	fAltitude;	// 1.0 ~ 0.0
	bool	bCanPass;
};

class Map
{
private:
	MAP_INFO** m_pMapInfo;
	size_t m_szX, m_szY;

public:
	Map();
	virtual ~Map(void);

	template<size_t x_sz> void SetMap(MAP_INFO pMap[][x_sz], size_t y_sz);
	template<size_t x_sz> void SetMap(bool (*pMap)[x_sz], size_t y_sz);
	template<size_t x_sz> void SetMap(float pMap[][x_sz], size_t y_sz);

	int FindRoute(POINTU from, POINTU to, std::list<POINTU>* pRoute) const;
	bool InRange(POINTU p) const { return p.x < m_szX && p.y < m_szY; }
};

////////////////////////////////////////////////////////////////////////////////////////////////
// Create memory of create information.
// And copy data to the memory.
//
#define BEGIN_COPY \
if (m_szY != y_sz) {	\
	for (ULONG y = m_szY; y > y_sz; --y) free(m_pMapInfo[y]);	\
	m_pMapInfo = (MAP_INFO**)_recalloc(m_pMapInfo, y_sz, sizeof(MAP_INFO*));	\
	_ASSERT(m_pMapInfo);	\
}	\
for (ULONG y = 0; y < y_sz; y++) {	\
	if (y >= m_szX || m_szX != x_sz)	\
		m_pMapInfo[y] = (MAP_INFO*)_recalloc(m_pMapInfo[y], x_sz, sizeof(MAP_INFO));	\
	_ASSERT(m_pMapInfo[y]);	\
	for (ULONG x = 0; x < x_sz; x++) {	\
//		COPY ELEMENT
#define END_COPY	\
	}	\
} m_szX = x_sz; m_szY = y_sz;


template<size_t x_sz>
void Map::SetMap(MAP_INFO pMap[][x_sz], size_t y_sz)
{
	BEGIN_COPY
		m_pMapInfo[y][x] = pMap[y][x];
	END_COPY
}

template<size_t x_sz>
void Map::SetMap(bool pMap[][x_sz], size_t y_sz)
{
	BEGIN_COPY
		m_pMapInfo[y][x].bCanPass = pMap[y][x];
	END_COPY
}

template<size_t x_sz>
void Map::SetMap(float pMap[][x_sz], size_t y_sz)
{
	BEGIN_COPY
		m_pMapInfo[y][x].fAltitude = pMap[y][x];
	END_COPY
}
